home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / imlib / oldjmalloc.c < prev    next >
C/C++ Source or Header  |  1996-04-11  |  14KB  |  561 lines

  1. #include <malloc.h>
  2. #include "jmalloc.hpp"
  3. #include <stdio.h>
  4. #include "macs.hpp"
  5. #include <string.h>
  6. #include "exitproc.hpp"
  7. #include "dprint.hpp" 
  8.  
  9.  
  10. #ifdef __WATCOMC__
  11. #include <dos.h>
  12. #include <new.h>
  13.  
  14.  
  15.  
  16. char *WAT_dos_alloc(long &size)
  17. {
  18.   union REGS r;
  19.   r.x.eax=0x0100;
  20.   r.x.ebx=(size+15)>>4;
  21.   int386(0x31,&r,&r);
  22.  
  23.   if (r.x.cflag)
  24.   {
  25.     size=(long)r.w.bx*16;
  26.     return NULL;
  27.   }
  28.   else 
  29.     return (char *)((r.x.eax&0xffff)<<4);
  30. }
  31.  
  32. void WAT_dos_free(void *ptr)
  33. {
  34.   union REGS r;
  35.   r.x.eax=0x0101;
  36.   r.x.edx=((long)ptr)>>4;
  37.   printf("free : segment is %d\n",r.w.dx);
  38.   int386(0x31,&r,&r);
  39.   if (r.x.cflag)
  40.     printf("DOS_free failed\n");
  41.  
  42. }
  43.  
  44. #endif
  45.  
  46. struct memory_node
  47. {
  48.   memory_node *next;
  49.   long size;
  50. #ifdef MEM_CHECK
  51.   char *name;                     // name is allocated on regular heap
  52. #endif                            // because it is used for debugging purposes
  53.                                   // and will probably be run on my linux box with VMM
  54.   memory_node *next_free;         // if free (size<0) this is a pointer to the next free block
  55.                                   // otherwise data starts here
  56. };
  57.  
  58.  
  59.  
  60. struct memory_block
  61. {
  62.   int type;
  63.   memory_node *fnode;
  64. } ;
  65.  
  66.  
  67. #define JM_SMALL_SIZE 128      // above 128 bytes is considered to be a big block and no hashing is done
  68.  
  69. memory_node *jm_small[JM_SMALL_SIZE/4];
  70. memory_node *jm_big;
  71.  
  72. memory_node *last_used=NULL;
  73.  
  74. #define MAX_BLOCKS 4
  75. long mem_blocks=0;
  76. memory_block blocks[MAX_BLOCKS];
  77.  
  78. #define REG_MEM    1
  79. #define LOW_MEM    2
  80. #define STATIC_MEM 3
  81.  
  82.  
  83. #ifdef MEM_CHECK
  84. void mem_check()
  85. {
  86.   int i,j;
  87.   for (i=0;i<mem_blocks;i++)
  88.   {
  89.     memory_node *last=blocks[i].fnode,*n;
  90.     for (j=0,n=last->next;n;n=n->next,j++)
  91.     {
  92.       if (last>=n)
  93.       {
  94.     printf("Memory corrupted, block #%d\n",j);
  95.     if (last->size>=0)
  96.       printf("last block name is %s\n",last->name);
  97.     else printf("last block was free\n");
  98.     mem_report("corrupt");
  99.       }
  100.     }    
  101.   }
  102.  
  103.  
  104. }
  105. #endif
  106.  
  107. void add_block(void *addr, long size, int type)
  108. {
  109.   if (mem_blocks<MAX_BLOCKS-1)
  110.   {   
  111.     blocks[mem_blocks].fnode=(memory_node *)addr;
  112.     blocks[mem_blocks].type=type;
  113.  
  114.     memory_node *f=blocks[mem_blocks].fnode;
  115.     f->size=-size+sizeof(memory_node)-sizeof(memory_node *);
  116.     f->next=NULL;
  117.     f->next_free=jm_big;
  118.     jm_big=f;
  119.     mem_blocks++;
  120.   }
  121.   else
  122.     fprintf(stderr,"added more than MEM_BLOCKS blocks\n");
  123. }
  124.  
  125. void *operator new( size_t size)
  126. {
  127.   return jmalloc(size,"::new object");
  128.  
  129. void operator delete(void *ptr)
  130. {
  131.   jfree(ptr);
  132. }
  133.  
  134. void jmem_cleanup(int ret, void *arg)
  135. { jmalloc_uninit(); }
  136.  
  137. void jmalloc_init(long min_size)  // allocates as much memory as possible, craps if min_size too big
  138. {
  139.   if (mem_blocks)
  140.     dprintf("warning : jmalloc_init called twice\n");
  141.   else
  142.   {
  143.     memset(jm_small,0,sizeof(memory_node *)*JM_SMALL_SIZE/4);      // clear out old free stacks
  144.     jm_big=NULL;
  145.  
  146.     exit_proc(jmem_cleanup,jmalloc_uninit);          // make sure memory gets freed up on exit
  147.  
  148.     void *mem_start;
  149.     long mem_size; 
  150.  
  151.     mem_start=NULL;
  152.  
  153.     for (mem_size=4000000;!mem_start && mem_size>0x4000;mem_size-=0x100)  // allocate 4 MB
  154.       mem_start=malloc(mem_size);
  155.     if (mem_start)
  156.     {
  157.       free(mem_start);
  158.       mem_size-=0x4000;
  159.       mem_start=malloc(mem_size);     // save some space on regular heap
  160.       dprintf("Memory subsystem : added high mem block (%d bytes)\n",mem_size);
  161.       add_block(mem_start,mem_size,REG_MEM);
  162.     }
  163.  
  164. #ifdef __WATCOMC__                      // allocate low memory from DOS
  165.     long dos_size=0xA0000;
  166.     char *dmem=(char *)WAT_dos_alloc(dos_size);
  167.     if (dmem) { printf("expecting dos_alloc to fail for %d bytes\n",0xa0000); }
  168.     if (dos_size<12000)
  169.       dprintf("Memory subsystem : low memory not used.. only %d bytes available\n",dos_size);
  170.     else
  171.     {
  172.       dos_size-=10000;   // 10k in case we need to for something else
  173.       dmem=(char *)WAT_dos_alloc(dos_size);
  174.       if (dmem)
  175.       {
  176.     add_block(dmem,dos_size,LOW_MEM);
  177.     dprintf("Memory subsystem : using %d bytes of low memory\n",dos_size);
  178.       } else dprintf("error in jmalloc_init\n");
  179.     }
  180. #endif
  181.  
  182.     
  183.     if (j_available()<min_size)
  184.     {
  185.       fprintf(stderr,"available memory = %d bytes, need %d\n",j_available(),min_size);
  186.       fprintf(stderr,"You do not have enough memory available!\n"
  187.           "  DOS users  : Make sure you have himem.sys or other extended memory\n"
  188.           "               manager running. (look in your config.sys)\n"
  189.           "               Can you remove any TSR/driver programs?\n"
  190.           "  UNIX users : Do you have a swap file/partition installed?\n"
  191.           "  MAC users  : I don't think so....... :)    -JC\n"); 
  192.       exit(0);
  193.     } 
  194.   }
  195. }
  196.  
  197. void jmalloc_uninit()
  198.   if (mem_blocks)
  199.   {
  200.     int i;
  201.     for (i=0;i<mem_blocks;i++)
  202.     {
  203.       switch (blocks[i].type)
  204.       {
  205.     case REG_MEM : 
  206.     { 
  207.       free((void *)blocks[i].fnode); } break;
  208. /*#ifdef __WATCOMC__         don't do this, because we don't know the segment numer
  209.                              and the memory manager will clean up for us...
  210.     case LOW_MEM : 
  211.     { WAT_dos_free(blocks[i].fnode); break; }
  212. #endif*/
  213.     case STATIC_MEM : break;
  214.     default :
  215.       dprintf("Memory subsystem : Unknow memory block type\n");
  216.       }
  217.     }
  218.     mem_blocks=0;
  219.   } else
  220.     dprintf("jmalloc_uninit :: jmalloc_init not called\n");
  221. }
  222.  
  223.  
  224. int join_blocks()
  225. {
  226.   int i,j=0;
  227.   memory_node *f=NULL;
  228.  
  229.   memset(jm_small,0,sizeof(memory_node *)*JM_SMALL_SIZE/4);      // clear out old free stacks
  230.   jm_big=NULL;
  231.  
  232.   for (i=0;!f && i<mem_blocks;i++)      
  233.   {
  234.     for (f=blocks[i].fnode;f;)
  235.     {
  236.       if (f->size<0)
  237.       {
  238.     if (!f->next || f->next->size>0)  // if next bock is not free and to stack
  239.     {
  240.       if (-f->size<JM_SMALL_SIZE)
  241.       {
  242.         f->next_free=jm_small[-f->size/4];
  243.         jm_small[-f->size/4]=f;
  244.       } else
  245.       {
  246.         f->next_free=jm_big;
  247.         jm_big=f;
  248.       }
  249.       f=f->next;
  250.     } else if (f->next && f->next->size<0)
  251.     {
  252.       f->size+=f->next->size-sizeof(memory_node)+sizeof(memory_node *);
  253.       f->next=f->next->next;
  254.       j=1;
  255.     }          
  256.       }
  257.       else f=f->next;
  258.     }
  259.   }
  260.   return j;
  261. }
  262.  
  263. void *jmalloc(long size, char *what_for)
  264. {
  265.   if (!mem_blocks)              // if not initialized, then use real malloc
  266.     return malloc(size);
  267. #ifdef MEM_CHECK
  268.   if (size<=0)     
  269.   {
  270.     size=4;
  271.     printf("jmalloc : asking for 0 or less\n");    
  272.   }
  273. #endif
  274.   size=(size+3)&(0xffffffff-3);      // make sure the size is word alligned
  275.  
  276.   while (1)     // loop until we find a block to return
  277.   {
  278.     if (size<JM_SMALL_SIZE && jm_small[size/4])  // see if we have a block this size already waiting
  279.     {
  280.       memory_node *find=jm_small[size/4];
  281.       find->size=-find->size;                 // mark as being used
  282. #ifdef MEM_CHECK
  283.       find->name=strcpy((char *)malloc(strlen(what_for)+1),what_for);
  284. #endif       
  285.       jm_small[size/4]=find->next_free;                       // pop the block from the free stack
  286.       return (void *)&find->next_free;
  287.     } else   
  288.     {
  289.       // find first block which will accomodate this size
  290.       // save the last pointer so we can compact the stack
  291.       memory_node *find=NULL,*f,*last=NULL;
  292.       for (f=jm_big;!find && f;f=f->next_free)
  293.         if (-f->size>=size)
  294.       find=f;
  295.         else last=f;
  296.  
  297.       if (find)
  298.       {
  299.     find->size=-find->size;                 // mark as being used
  300. #ifdef MEM_CHECK
  301.     find->name=strcpy((char *)malloc(strlen(what_for)+1),what_for);
  302. #endif            
  303.     if (last)
  304.       last->next_free=find->next_free;
  305.     else
  306.       jm_big=find->next_free;                    // pop the block from the free stack
  307.     if (find->size-size>sizeof(memory_node))     // enough space for free block?
  308.     {
  309.       memory_node *new_free=(memory_node *)(((char *)(&find->next_free))+size);
  310.       new_free->size=(find->size+sizeof(memory_node *)-size-sizeof(memory_node));
  311.       find->size=size;
  312.       if (new_free->size<JM_SMALL_SIZE)
  313.       {
  314.         new_free->next_free=jm_small[new_free->size/4];
  315.         jm_small[new_free->size/4]=new_free;
  316.       } else
  317.       {
  318.         new_free->next_free=jm_big;
  319.         jm_big=new_free;        
  320.       }      
  321.       new_free->next=find->next;
  322.       find->next=new_free;
  323.       new_free->size=-new_free->size;           // mark this block as free
  324.     }
  325.     return (void *)&find->next_free;
  326.       } else if (!join_blocks())
  327.         free_up_memory();
  328.     }
  329.   }
  330. }
  331.  
  332.  
  333. /*    // start at the last spot we used and see if we can find a block near there
  334.     if (last_used && (last_used->size<0) && ((-last_used->size-reserve)>=size))
  335.         f=last_used;
  336.  
  337.     if (!f)     // no block yet, scan for one.
  338.     {
  339.       int i;
  340.       for (i=0;!f && i<mem_blocks;i++)      
  341.       {
  342.         for (f=blocks[i].fnode;f && (f->size>=0 || -f->size-reserve<=size);f=f->next);      
  343.       }
  344.     }
  345.     if (!f && !join_blocks())
  346.       free_up_memory();                       // user defined function to free memory
  347.     else
  348.     {
  349.       if (size>=-f->size-reserve)             // allocating the whole block?
  350.       {
  351.     f->size=-f->size;                     // chain stays the same, but mark memory as used
  352. #ifdef MEM_CHECK
  353.     f->name=strcpy((char *)malloc(strlen(what_for)+1),what_for);
  354. #endif      
  355.     last_used=f->next;                    // use next spot as refrence spot
  356.       }
  357.       else                                    // else create a new free node
  358.       {
  359.     memory_node *new_free;
  360.     new_free=(memory_node *)(((unsigned char *)f)+size+sizeof(memory_node));    
  361.     new_free->next=f->next;
  362.     new_free->size=f->size+size+sizeof(memory_node);
  363.  
  364.     f->next=new_free;
  365.     f->size=size;
  366.     last_used=new_free;
  367. #ifdef MEM_CHECK
  368.     f->name=strcpy((char *)malloc(strlen(what_for)+1),what_for);
  369. #endif      
  370.       }
  371.       return (void *)(((unsigned char *)(f))+sizeof(memory_node));
  372.     }
  373.   } 
  374.   return NULL; // while never happen 
  375. } */
  376.  
  377.  
  378. void jfree(void *ptr)
  379. {
  380.   if (!mem_blocks)
  381.     free(ptr);
  382.   else
  383.   {
  384.     memory_node *f=(memory_node *)(((char *)ptr)+sizeof(memory_node *)-sizeof(memory_node));   
  385. #ifdef MEM_CHECK
  386.     if (f->size<0)
  387.     {
  388.       printf("Bad pointer\n");
  389.       return ;
  390.     }
  391.     free(f->name);
  392. #endif
  393.     if (f->size<JM_SMALL_SIZE)    // insert into small block chain?
  394.     {
  395.       f->next_free=jm_small[f->size/4];
  396.       jm_small[f->size/4]=f;
  397.     }
  398.     else
  399.     {
  400.       f->next_free=jm_big;
  401.       jm_big=f;
  402.     }
  403.     f->size=-f->size;   // mark free and join blocks later
  404.   }
  405. }
  406.  
  407.  
  408. void *jrealloc(void *ptr, long size, char *what_for)
  409. {
  410.   if (!mem_blocks)
  411.   {
  412.     if (ptr)                     // some platforms don't do this!
  413.       return realloc(ptr,size);
  414.     else return malloc(size);
  415.   }
  416.  
  417.   if (!ptr)
  418.     return jmalloc(size,what_for);
  419.   else
  420.   {
  421.     if (size==0)                    // if the new size needed is zero then we can throw this away.
  422.     {      
  423.       jfree(ptr);
  424.       return NULL;
  425.     }
  426.     else
  427.     {
  428.       memory_node *f=(memory_node *)(((char *)ptr)+sizeof(memory_node *)-sizeof(memory_node));
  429.       long old_size=f->size;       // for now we are not going to be very smart about our re-allocation
  430.                                   // i.e. just allocate another block and copy this into it.
  431.       void *new_loc=jmalloc(size,what_for);  
  432.  
  433.       if (size>old_size)
  434.         memcpy(new_loc,ptr,old_size);
  435.       else
  436.         memcpy(new_loc,ptr,size);
  437.  
  438.       jfree(ptr);
  439.       return new_loc;
  440.     }
  441.   }
  442.   return NULL;
  443. }
  444.  
  445.  
  446. long j_allocated()
  447. {
  448.   memory_node *f;
  449.   long s=0,i;
  450.   for (i=0;i<mem_blocks;i++)
  451.   {
  452.     for (f=blocks[i].fnode;f;f=f->next)
  453.     {
  454.       if (f->size>0)
  455.       s+=f->size;
  456.     }
  457.   }
  458.   return s;
  459. }
  460.  
  461. long j_available()
  462. {
  463.   memory_node *f;
  464.   long s=0,i;
  465.   for (i=0;i<mem_blocks;i++)
  466.   {
  467.     if (!blocks[i].fnode)
  468.       printf("block #%d is NULL\n",i);
  469.  
  470.     for (f=blocks[i].fnode;f;f=f->next)
  471.     {
  472.       if (f->size<0)
  473.         s+=-f->size;
  474.     }
  475.   }
  476.   return s;
  477. }
  478.  
  479.  
  480.  
  481. void mem_report(char *filename)
  482. {
  483.   long tot=0;
  484.   FILE *fp=fopen(filename,"wb");
  485.   int size_count[64];
  486.   memset(size_count,0,sizeof(size_count));
  487.   if (fp)
  488.   {
  489.     long i,size,tblocks=0;
  490.     for (i=0;i<mem_blocks;i++)
  491.     {
  492.       fprintf(fp,"*************** MEMORY BLOCK #%d ****************\n",i);
  493.       long offset=0;
  494.       memory_node *p=blocks[i].fnode;
  495.       while (p)
  496.       {
  497.     if (p->size>=0)
  498.     {
  499.       tblocks++;
  500.       if (p->size<64)
  501.         size_count[p->size]++;
  502.     }
  503.  
  504.     if (p==last_used)
  505.       fprintf(fp,"-> ");
  506. #ifdef MEM_CHECK
  507.     if (p->size<0)
  508.           fprintf(fp,"%10d %d  %s\n",offset,p->size,"FREE");
  509.     else
  510.           fprintf(fp,"%10d %d  %s\n",offset,p->size,p->name);
  511. #else
  512.     fprintf(fp,"%10d %d\n",offset,p->size);
  513. #endif
  514.     offset+=(abs(p->size)+sizeof(memory_node));
  515.     tot+=abs(p->size);
  516.     p=p->next;
  517.       }
  518.     }
  519.     fprintf(fp,"##  Total = %d bytes\n",tot);
  520.     fprintf(fp,"##  Total allocated = %d bytes\n",j_allocated());
  521.     fprintf(fp,"##  Total blocks = %d\n",tblocks);
  522.  
  523.  
  524.     for (i=0;i<JM_SMALL_SIZE/4;i++)
  525.     {
  526.       memory_node *f=jm_small[i];
  527.       if (f)
  528.       { 
  529.     int t;
  530.     fprintf(fp,"Size %d : Free = ",i*4);
  531.     for (t=0;f;f=f->next_free,t++)
  532.           if (-f->size!=i*4)
  533.         fprintf(fp,"  bad size! (%d)\n",f->size);
  534.  
  535.     int tb=0;
  536.     for (int j=0;j<mem_blocks;j++)
  537.     {
  538.       memory_node *p=blocks[j].fnode;
  539.       for (;p;p=p->next)
  540.         if (p->size==i*4)
  541.           tb++;
  542.     }
  543.     
  544.     fprintf(fp,"%d, Used = %d\n",t,tb);
  545.  
  546.       }
  547.     }
  548.  
  549.   }
  550.   fclose(fp);
  551. }
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.